﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Xml;

namespace InfoPathHelpers.Cryptography
{
    public static class X509Helper
    {
        /// <summary>
        /// Gets the certificate with the supplied subject from the personal store on the current PC.
        /// </summary>
        /// <param name="certificateSubject">The subject of the certificate to get.</param>
        /// <returns>an X509Certificate2 object corresponding to the certifcate matching the supplied subject; 
        /// or null if the certifcate could not be located.</returns>
        public static X509Certificate2 GetCertificateBySubject(string certificateSubject)
        {
            // Open the certificates store.
            var Store = new X509Store(StoreName.My);
            Store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

            // Place all certificates in an X509Certificate2Collection object.
            var Certificates = new X509Certificate2Collection();

            foreach (var Certificate in Store.Certificates)
            {
                if (Certificate.Subject == certificateSubject)
                {
                    return Certificate;
                }
            }

            return null;
        }

        /// <summary>
        /// Opens a certicate selection UI for the user to select one certificate from all certificate with private keys.
        /// </summary>
        /// <param name="storeName">The name of the store to select certificates from.</param>
        /// <returns>The certificate selected by the user of null if they cancelled.</returns>
        /// <exception cref="ArgumentException">Thrown if the supplied store contains no private key certificates.</exception>
        public static X509Certificate2 SelectPrivateKeysFromStore(StoreName storeName, string message)
        {
            // Open the certificates store.
            var Store = new X509Store(storeName);
            Store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

            // Place all certificates in an X509Certificate2Collection object.
            var Certificates = new X509Certificate2Collection();

            X509Certificate2 SelectedCertificate = null;

            // Filter certificates with private keys.
            foreach (var Certificate in Store.Certificates)
            {
                if (Certificate.HasPrivateKey)
                {
                    Certificates.Add(Certificate);
                }
            }

            if (Certificates.Count == 0)
            {
                throw new ArgumentException("The supplied certificate store contains no valid certificates", "storeName");
            }

            // Show selection UI only if there are certificates to choose from.
            X509Certificate2Collection SelectedCertificates = X509Certificate2UI
                .SelectFromCollection(Certificates, "Select Certificate", message,
                X509SelectionFlag.SingleSelection);
           
            if(SelectedCertificates.Count > 0)
            {
                SelectedCertificate = SelectedCertificates[0];
            }

            // Close the store.
            Store.Close();

            return SelectedCertificate;
        }
    }
}
